﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;
using log4net.Config;
namespace PlayerStat
{
    public class MatchData
    {
        public int LeagueID
        {
            get;
            set;
        }

        public int MatchRound
        {
            get;
            set;
        }

        public int matchID;
        public DateTime matchTime;
        public string home;
        public string away;
        public int homeID;
        public int awayID;
        public MatchStat match = new MatchStat();
        public Dictionary<int, PlayerStat> homeplayers = new Dictionary<int,PlayerStat>();
        public Dictionary<int, PlayerStat> awayplayers = new Dictionary<int, PlayerStat>();
        private ILog logger = null;

        public MatchData()
        {
            logger = LogManager.GetLogger("Scrape");
        }

        public bool SaveToDB()
        {
            DBUtil util = new DBUtil();

            try
            {
                // validate team, if not exist then add
                homeID = ValidateTeam(util, LeagueID, home);
                // validate team, if not exist then add
                awayID = ValidateTeam(util, LeagueID, away);

                //Save match statistic data
                matchID = SaveMatchStat(util);
                logger.Debug("Save match's statistic data");

                SavePlayerStat(util, LeagueID, matchID, matchTime, homeID, ref homeplayers);

                SavePlayerStat(util, LeagueID, matchID, matchTime, awayID, ref awayplayers);

                return true;
            }
            catch (Exception ex)
            {
                logger.Error(ex.ToString());
                return false;
            }
        }
        
        //Save the match statistic data to DB and return the MatchID
        private int SaveMatchStat(DBUtil util)
        {
            tblMatch tbl_match = new tblMatch();
            tbl_match.LeagueID = LeagueID;
            tbl_match.MatchRound = MatchRound;
            tbl_match.EventTime = matchTime;
            tbl_match.HomeTeamID = homeID;
            tbl_match.HomeScore = match.homeScore;
            tbl_match.HomeYellowCard = match.homeYCard;
            tbl_match.HomeRedCard = match.homeRCard;
            tbl_match.AwayTeamID = awayID;
            tbl_match.AwayScore = match.awayScore;
            tbl_match.AwayYellowCard = match.awayYCard;
            tbl_match.AwayRedCard = match.awayRCard;
            util.dbClass.tblMatches.InsertOnSubmit(tbl_match);
            util.dbClass.SubmitChanges();
            return tbl_match.MatchID;
        }

        //Save the match statistic data to DB and return the MatchID
        private void SavePlayerStat(DBUtil util, int leagueID, int matchID, DateTime time, int teamID, ref Dictionary<int, PlayerStat> players)
        {
            foreach (PlayerStat p in players.Values)
            {
                p.leagugeID = leagueID;
                p.teamID = teamID;
                p.matchID = matchID;
                p.playerKey = ValidatePlayer(util, matchTime, p);
                tblPlayerStat ps = new tblPlayerStat();
                ps.PlayerKey = p.playerKey;
                ps.IsPlayerSub = p.isPlayerSub;
                ps.MarkingID = p.markID;
                ps.MatchID = p.matchID;
                ps.PlayerPosID = p.posID;
                ps.PlayerGoal = p.goal;
                ps.PlayerOwnGoal = p.owngoal;
                ps.PlayerYellowCard = p.yellowCard;
                ps.PlayerRedCard = p.redCard;
                util.dbClass.tblPlayerStats.InsertOnSubmit(ps);
                util.dbClass.SubmitChanges();

                foreach (MinuteStat ms in p.MinStat)
                {
                    tblPlayerMinuteStat pms = new tblPlayerMinuteStat();
                    pms.PlayerStatID = ps.PlayerStatID;
                    pms.IsOwnGoal = ms.isOwnGoal;
                    pms.PlayerGoalMinute = ms.goalMin;
                    util.dbClass.tblPlayerMinuteStats.InsertOnSubmit(pms);
                    util.dbClass.SubmitChanges();
                }

                if (p.yCardMin1 != -1)
                {
                    tblPlayerMinuteStat pms = new tblPlayerMinuteStat();
                    pms.PlayerStatID = ps.PlayerStatID;
                    pms.PlayerYellowCardMinute1 = p.yCardMin1;
                    util.dbClass.tblPlayerMinuteStats.InsertOnSubmit(pms);
                    util.dbClass.SubmitChanges();
                }

                if (p.rCardMin != -1)
                {
                    tblPlayerMinuteStat pms = new tblPlayerMinuteStat();
                    pms.PlayerStatID = ps.PlayerStatID;
                    pms.PlayerRedCardMinute = p.rCardMin;
                    util.dbClass.tblPlayerMinuteStats.InsertOnSubmit(pms);
                    util.dbClass.SubmitChanges();
                }
            }
        }
        
        // Validate team, if team exists return the teamID, if not add team
        private int ValidateTeam(DBUtil util, int leagueID, string team)
        {
            int id = 0;
            if (util.GetTeamID(leagueID, team, ref id))
            {
                return id;
                //teamID found
            }
            else if (id == -1)
            {
                //teamID not found
                tblTeam tbl_team = new tblTeam();
                tbl_team.TeamName = team;
                util.dbClass.tblTeams.InsertOnSubmit(tbl_team);
                util.dbClass.SubmitChanges();
                return tbl_team.TeamID;
            }
            else
            {
                throw new Exception("#ValidateTeam# Failed to validate team.");
            }
        }
        
        private int ValidatePlayer(DBUtil util, DateTime dt, PlayerStat player)
        {
            List<tblPlayer> result = null;
            if (util.GetPlayer(player.playerName, out result))
            {
                tblPlayer temp = null;
                foreach (tblPlayer p in result)
                {
                    if (p.PlayerID == player.playerID && p.PlayerLeagueID == player.leagugeID)
                    {
                        if (p.PlayerTeamID == player.teamID)
                        {
                            return p.PlayerKey;
                        }
                        else
                        {
                            temp = p;
                        }
                    }
                }
                if (temp == null)
                {
                    // new player for the league
                    tblPlayer pl = new tblPlayer();
                    pl.PlayerID = player.playerID;
                    pl.PlayerLeagueID = player.leagugeID;
                    pl.PlayerName = player.playerName;
                    pl.PlayerTeamID = player.teamID;
                    pl.PlayerTeamFrom = dt.Date;
                    pl.PlayerTeamTo = DateTime.Parse("9999/12/31");
                    util.dbClass.tblPlayers.InsertOnSubmit(pl);
                    util.dbClass.SubmitChanges();
                    return pl.PlayerKey;
                }
                else
                {
                    // a player is transfered to another team in the league
                    // update the transfer date
                    temp.PlayerTeamTo = dt.AddDays(-1.0).Date;
                    util.dbClass.SubmitChanges();

                    // add a new player with same playerID
                    tblPlayer pl = new tblPlayer();
                    pl.PlayerID = player.playerID;
                    pl.PlayerLeagueID = player.leagugeID;
                    pl.PlayerName = player.playerName;
                    pl.PlayerTeamID = player.teamID;
                    pl.PlayerTeamFrom = dt.Date;
                    pl.PlayerTeamTo = DateTime.Parse("9999/12/31");
                    util.dbClass.tblPlayers.InsertOnSubmit(pl);
                    util.dbClass.SubmitChanges();
                    return pl.PlayerKey;
                }
            }
            else
            {
                // new player to insert
                tblPlayer pl = new tblPlayer();
                pl.PlayerID = player.playerID;
                pl.PlayerLeagueID = player.leagugeID;
                pl.PlayerName = player.playerName;
                pl.PlayerTeamID = player.teamID;
                pl.PlayerTeamFrom = dt.Date;
                pl.PlayerTeamTo = DateTime.Parse("9999/12/31");
                util.dbClass.tblPlayers.InsertOnSubmit(pl);
                util.dbClass.SubmitChanges();
                return pl.PlayerKey;
            }
        }
        
        public bool ExistInDB()
        {
            DBUtil util = new DBUtil();
            return util.ExistInDB(home, away,matchTime);
        }
    }
}
